<?php

/**
 * 聚水潭 SDK
 * @author chenyun
 */

namespace App\Service\VendorClient\Shopjushuitan;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;
use Swoole\Coroutine\WaitGroup;
use App\Model\PssModel\ServiceConfig;

class ShopjushuitanApiClient
{
    private $account  = 'shopjushuitan';
    protected $config;
    protected $RouteMap = [
        'createOrder'          => '/open/jushuitan/orders/upload',
        'cancelOrder'          => '/open/jushuitan/orderbyoid/cancel',
        'queryGoodsList'       => '/open/sku/query',
        'queryGoodsQty'        => '/open/inventory/query',
    ];
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $params = [] ) 
    {   
        ini_set('serialize_precision', 16);
        if( empty($params['supplierOrder']) || empty($params['orderGoods'])) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $supplier_skuid_map = [];
        if(isset($this->config["mode"]) && $this->config["mode"] != "derect"){
            $supplier_skuid_map = $params['supplier_skuid_map'];
        }
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        //商品下单组
        $items = [];
        $totalGoodsMoney = $productAmt = $freight = $TaxAmt = 0 ;
        foreach ($params['orderGoods'] as $key => $item )
        {
            //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量
            $buyAcount          = $spec_num * $quantity ;
            //如果商品除不尽，得多取以为，减去实际金额为折扣，折扣不能为负数
            if( $key == 0 ) {
                $singleDeliveryMoney = bcdiv((string)$deliver_money,(string)$quantity,3);
                $singleDeliveryMoney = bcmul((string)$singleDeliveryMoney,(string)100,1);
                $singleDeliveryMoney = bcdiv((string)ceil($singleDeliveryMoney), (string)100,2);
                $price               = bcadd((string)$price, (string)$singleDeliveryMoney,2);
            }
            //单个商品价格
            $singleGoodsPrice   = bcdiv((string)$price, (string)$spec_num,3);
            $singleGoodsPrice   = ceil(bcmul((string)$singleGoodsPrice,(string)'100',1));
            $singleGoodsPrice   = bcdiv((string)$singleGoodsPrice,'100',2);
            $totalGoods         = bcmul((string)$singleGoodsPrice,(string)$buyAcount,2);

            //含税税率
            $tax_rate           = bcadd('1', (string)$item['tax_rate'],4);
            //不含税价格
            $not_tax_price      = bcdiv((string)$singleGoodsPrice, (string)$tax_rate,3);
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = ceil(bcmul((string)$not_tax_price,(string)'100',1));
            // echo "含税税率:".$tax_rate."不含税价格：".$not_tax_price;
            $not_tax_price      = bcdiv((string)$not_tax_price,'100',2);
            
            //税金
            $singleGoodsTax     = bcsub((string)$singleGoodsPrice, (string)$not_tax_price,3);
            
            //单个商品总税金
            $totalGoodsTax  = bcmul((string)$singleGoodsTax,(string)$buyAcount,2);
            
            //单个商品总不含税价格
            $totalGoods     = bcmul((string)$singleGoodsPrice,(string)$buyAcount,2);
            
            if(isset($this->config["mode"]) && $this->config["mode"] == "derect"){
                $supplier_skuid = $item['supplier_skucode'];
            }else{
                if(empty($supplier_skuid_map[$item['supplier_skuid']])){
                    return Normal::returnCode(Normal::FAIL,"供应商商品ID".$item['supplier_skuid']."的菜鸟备案id不存在，请核实！");
                }
                $supplier_skuid = $supplier_skuid_map[$item['supplier_skuid']];
            }
            $outer_oi_id = $supplier_skuid.$key;
            //商品组
            $items[] = [
                'sku_id'        => (string)$item['supplier_skucode'],
                'shop_sku_id'   => (string)$supplier_skuid,
                'amount'        => (float)$totalGoods,
                'base_price'    => (float)$totalGoods,
                'qty'           => (int)$buyAcount,
                'name'          => (string)$item['goods_name'],
                'outer_oi_id'   => (string)$outer_oi_id,
            ];
        
            $productAmt = bcadd((string)$productAmt,(string)$totalGoods,2);
            $TaxAmt = bcadd((string)$TaxAmt,(string)$totalGoodsTax,2);
        }
        //实际下单金额
        $real_total_money = $orderInfo['real_total_money'];
        //优惠金额
        $discountMoney      = $orderInfo['discountMoney'] ?? 0.00;
        //总运费(运费 +运费税)
        $delivery       = bcadd((string)$freight, 0.00,2);
        //下单总金额(商品总金额 + 总运费)
        $totalMoney     = bcadd((string)$totalGoodsMoney,(string)$delivery,2);
        //下单支付的时候支付信息
        $apply_extends  = @json_decode($orderInfo['apply_extends'],true);
        //支付时间
        $payTime        = $orderInfo['pay_time'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $pay_time       = date('Y-m-d H:i:s',$pay_time);
        
        //支付流水号
        $pay_sn         = $order['paySerial']??$orderInfo['pay_sn'];
        
        //判断商品类型
        if($params['orderGoods'][0]["goods_type"] != 0){
            //获取上游供应商支付方式路由
            $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
            $pay_value      = ServiceConfig::instance()->getConfigByEventsValue($this->account, ServiceConfig::TYPE_PAY, $payCommanyCode);
            if (empty($pay_value)) {
                return Normal::returnCode(Normal::FAIL, "支付公司编码：【{$payCommanyCode}】未映射，请联系管理员处理");
            }
        }else{
            $pay_value = "其他";
        }
        $pay_info       = [
            "outer_pay_id"  => (string)$pay_sn,
            "pay_date"      => (string)$pay_time,
            "payment"       => (string)$pay_value,
            "buyer_account" => (string)$orderInfo['buyer_phone'],
            "seller_account"=> "其他",
            "buyer_account" => "其他",
            "amount"        => (float)$real_total_money,
        ];
        $card_info      = [
            "name"          => (string)$orderInfo['buyer_realname'],
            "card_id"       => (string)$orderInfo['buyer_idcard'],
        ];
        $timestamp=time();
        $data = [
            'shop_id'               => (int)$this->config['shop_id'],
            'so_id'                 => (string)$orderInfo['supplier_dsn'],
            'order_date'            => date("Y-m-d H:i:s",time()),
            'shop_status'           => "WAIT_SELLER_SEND_GOODS",
            'shop_buyer_id'         => (string)$orderInfo['buyer_phone'],
            'receiver_state'        => $orderInfo['province'],
            'receiver_city'         => $orderInfo['city'],
            'receiver_district'     => $orderInfo['district'],
            'receiver_address'      => $orderInfo['receive_address'],
            'receiver_name'         => $orderInfo['receive_name'],
            'receiver_phone'        => (string)$orderInfo['recveive_phone'],//座机
            'receiver_mobile'       => (string)$orderInfo['recveive_phone'],//手机
            'pay_amount'            => (float)$real_total_money,
            'freight'               => (float)$delivery,
            'buyer_message'         => $orderInfo["order_remark"]??"尽快发货",
            'l_id'                  => $orderInfo["express_sn"],
            'logistics_company'     => $orderInfo["express_name"],
            'items'                 => $items,
            'pay'                   => $pay_info,
            'card'                  => $card_info, 
        ];
        if(isset($this->config['wms_co_id'])){
            $data["wms_co_id"] = (int)$this->config['wms_co_id']; 
        }
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => json_encode([$data],JSON_UNESCAPED_UNICODE),
        ];
        $res =  $this->execute($requestParam);
        if( $res['code'] == Normal::SUC ) {
            return Normal::returnCode(Normal::SUC,"订单推送成功",[
                'thirdpart_order_sn' => $res["data"]["datas"][0]['o_id']
            ]);
        }
        return $res;
    }
    
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] )
    {
        $orderSupplier      = $params['supplierOrder'];
        $order              = $params['order'];
        $data = [
            'o_ids'         => [$orderSupplier["thirdpart_order_sn"]],
            'cancel_type'   => "不需要了",
            'remark'        => $order['exceptReason'] ?? '申请订单退款作废,不要了',
        ];
        $requestParam = [
            'method'    => 'cancelOrder',
            'data'      => json_encode($data,JSON_UNESCAPED_UNICODE),
        ];
        $res = $this->execute($requestParam);
        return $res;
    }
    /**
     * 查询商品信息
     */
    public function queryGoodsList( $params = [] )
       {
        //获取7天以内修改的商品数据
        $modified_begin = date("Y-m-d H:i:s", strtotime("-7 day"));
        $modified_end   = date("Y-m-d H:i:s",time());
        $biz = [
            'page_index'    => $params["page"],
            'page_size'     => 50,
            'modified_begin'=> $modified_begin,
            'modified_end'  => $modified_end,
            'date_field'    => "modified",
            //'sku_ids' => "56709260002801"
        ];
        $requestParam = [
            'method'    => 'queryGoodsList',
            'data'      => json_encode($biz,JSON_UNESCAPED_UNICODE),
        ];
        $newData =[];
        $res = $this->execute($requestParam);
        if( $res['code'] == Normal::SUC ) {
            $newData  = $res['data']['datas'];
            //批量获取商品库存
            $skuIds_list = array_column($newData,'sku_id');
            $sku_ids[] = join(",",$skuIds_list);
            $resDetails = $this->queryGoodsDetails($sku_ids);
            //开始组装数据
            foreach($newData as $key =>$value){
                $newData[$key]['qty'] = 0;
                if(isset($resDetails[$value['sku_id']])){
                    $newData[$key]['qty'] = $resDetails[$value['sku_id']];  
                }
            } 
            return Normal::returnCode(Normal::SUC,"操作成功",array('list' =>$newData,'total' => $res['data']['data_count'] ?? 0,'has_next' => $res["data"]["has_next"]));
        }
        return $res;
    }
    //查询商品库存
    public function queryGoodsDetails($sku_ids){
        $details = [];
        $count = count($sku_ids);
        $wg = new WaitGroup();
        $wg->add($count);
        foreach ($sku_ids as $sku_id){
            co(function () use ($wg,$sku_id,& $details) {
                $requestParam = [
                    'sku_id' => $sku_id,
                ];
                $responseParam = $this->queryGoodsQty($requestParam);
                if($responseParam["code"] == 200 && !empty($responseParam["data"]["inventorys"])){
                    foreach ($responseParam['data']["inventorys"] as $inventorys){
                        $details[$inventorys["i_id"]] = $inventorys["qty"];
                    }
                }
                $wg->done();
            });
        }
        $wg->wait();
        return $details;
    }

    /**
     * 查询商品库存
     */
    public function queryGoodsQty( $params = [] )
    {
        $biz = [
            'page_size'  => 1,
            'page_size'  => 50,
            'sku_ids'    => $params["sku_id"],
        ];
        $requestParam = [
            'method'    => 'queryGoodsQty',
            'data'      => json_encode($biz,JSON_UNESCAPED_UNICODE),
        ];
        $res = $this->execute($requestParam);
        return $res;
    }
    /**
     * 加签
     * @param array $param
     */
    protected function getSign($app_secret,$data)
    {
        if ($data == null) {
            return null;
        }
        ksort($data);
        $result_str = "";
        foreach ($data as $key => $val) {
            if ( $key != null && $key != "" && $key != "sign" ) {
                $result_str = $result_str . $key . $val;
            }
        }
        $result_str = $app_secret . $result_str;
        $ret = bin2hex(md5($result_str, true));
        return $ret;
    }
    /**
     * CURL请求-0
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )  
    {  
        if(empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method     = $param['method'];
        $url        = $this->config['baseurl'].$this->RouteMap[$method];
        $app_secret = $this->config['app_secret'];
        $data=[
            "app_key"       =>$this->config["app_key"],
            "access_token"  =>$this->config["access_token"],
            "timestamp"     =>time(),
            "charset"       =>"utf-8",
            "version"       =>"2",
            "biz"           =>$param["data"],
        ];
        $data["sign"] = $this->getSign($app_secret,$data);
        $parameter = [
             [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $url,
                'data'      => $data,
                'method'    => 'post',
                'format'    => 'x-www-form-urlencoded',
                'header'    => [
                    "application/x-www-form-urlencoded;charset=UTF-8",
                ],
        
            ],
        ];
        if( in_array($method,['queryGoodsList','queryGoodsQty']) ) {
            $resTask = TaskWorker::instance()->addTask($parameter,'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        $resTask = current($resTask);
        $res     = $resTask['response']['result']; 
        $resHttp = @json_decode($res, true);
        if( isset($resHttp['code']) && $resHttp['code']==0 ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp["data"]);
        }
        $message = isset($resHttp['msg']) ? $resHttp['msg'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
    
}